package com.xhwl.logistics.service.cent.server;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xhwl.common.dto.cent.vehicle.feign.CreateVehicleAccessRecordForInNanTouFeignDTO;
import com.xhwl.common.dto.cent.vehicle.feign.CreateVehicleAccessRecordForOutNanTouFeignDTO;
import com.xhwl.logistics.bo.cent.ProjectBO;
import com.xhwl.logistics.converter.mapstruct.VehicleAccessRecordConverter;
import com.xhwl.logistics.converter.mapstruct.VehiclePayRecordConverter;
import com.xhwl.logistics.entity.VehicleAccessRecord;
import com.xhwl.logistics.entity.VehiclePayRecord;
import com.xhwl.logistics.service.cent.QueryProjectService;
import com.xhwl.logistics.service.impl.VehicleAccessRecordServiceImpl;
import com.xhwl.logistics.service.impl.VehiclePayRecordServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.util.Optionals;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

@Slf4j
//@Service
public class VehicleAccessRecordNanTouFeignServiceImpl implements IVehicleAccessRecordNanTouFeignService{

    @Autowired
    private QueryProjectService queryProjectService;

    @Autowired
    private VehicleAccessRecordServiceImpl vehicleAccessRecordService;

    @Autowired
    private VehiclePayRecordServiceImpl vehiclePayRecordService;

    @Autowired
    private VehicleAccessRecordConverter vehicleAccessRecordConverter;

    @Autowired
    private VehiclePayRecordConverter payRecordConverter;

    private void nestedConditionForAccessRecord(LambdaQueryWrapper<VehicleAccessRecord> lambdaQueryWrapper, CreateVehicleAccessRecordForOutNanTouFeignDTO createVehicleAccessRecordForOutNanTouFeignDTO) {
        lambdaQueryWrapper.eq(VehicleAccessRecord::getProjectId, createVehicleAccessRecordForOutNanTouFeignDTO.getProjectId())
                .eq(VehicleAccessRecord::getParkId, createVehicleAccessRecordForOutNanTouFeignDTO.getParkId())
                .eq(VehicleAccessRecord::getPlateNumber, createVehicleAccessRecordForOutNanTouFeignDTO.getPlateNumber())
                .eq(VehicleAccessRecord::getEnterTime, createVehicleAccessRecordForOutNanTouFeignDTO.getEnterTime());
    }

    private boolean judgeForPay(CreateVehicleAccessRecordForOutNanTouFeignDTO createVehicleAccessRecordForOutNanTouFeignDTO) {
        return !(createVehicleAccessRecordForOutNanTouFeignDTO.getTotalMoney().equals(0) && createVehicleAccessRecordForOutNanTouFeignDTO.getPaidMoney().equals(0));
    }

    @Override
    public void addAccessRecordsForIn(List<CreateVehicleAccessRecordForInNanTouFeignDTO> createVehicleAccessRecordForInNanTouFeignDTOList) {
        if (createVehicleAccessRecordForInNanTouFeignDTOList.isEmpty()) {
            log.info("access record for in nan-tou is empty, feign call do nothing!");
            return;
        }

        Integer projectId = createVehicleAccessRecordForInNanTouFeignDTOList.get(0).getProjectId();
        ProjectBO projectBO = queryProjectService.queryProject(projectId);

        List<VehicleAccessRecord> vehicleAccessRecordList = vehicleAccessRecordConverter.toVehicleAccessRecordList(createVehicleAccessRecordForInNanTouFeignDTOList, projectBO);
        vehicleAccessRecordService.saveBatch(vehicleAccessRecordList);
    }

    @Override
    @Transactional
    public void addAccessRecordsForOut(List<CreateVehicleAccessRecordForOutNanTouFeignDTO> createVehicleAccessRecordForOutNanTouFeignDTOList) {
        if (createVehicleAccessRecordForOutNanTouFeignDTOList.isEmpty()) {
            log.info("access record for out nan-tou is empty, feign call do nothing!");
            return;
        }

        Integer projectId = createVehicleAccessRecordForOutNanTouFeignDTOList.get(0).getProjectId();
        ProjectBO projectBO = queryProjectService.queryProject(projectId);

        LambdaQueryWrapper<VehicleAccessRecord> wrapper = new LambdaQueryWrapper();
        createVehicleAccessRecordForOutNanTouFeignDTOList.forEach(createVehicleAccessRecordForOutNanTouFeignDTO -> wrapper.or(condition -> nestedConditionForAccessRecord(condition, createVehicleAccessRecordForOutNanTouFeignDTO)));
        List<VehicleAccessRecord> vehicleAccessRecordList = vehicleAccessRecordService.list(wrapper);

        List<VehicleAccessRecord> add = new ArrayList<>();
        List<VehicleAccessRecord> update = new ArrayList<>();
        List<VehiclePayRecord> payForAdd = new ArrayList<>();
        for (CreateVehicleAccessRecordForOutNanTouFeignDTO createVehicleAccessRecordForOutNanTouFeignDTO : createVehicleAccessRecordForOutNanTouFeignDTOList) {
            String plateNumber = createVehicleAccessRecordForOutNanTouFeignDTO.getPlateNumber();
            Date enterTime = createVehicleAccessRecordForOutNanTouFeignDTO.getEnterTime();
            Optional<VehicleAccessRecord> optionalVehicleAccessRecord = vehicleAccessRecordList.stream()
                    .filter(vehicleAccessRecord -> plateNumber.equals(vehicleAccessRecord.getPlateNumber()) && enterTime.equals(vehicleAccessRecord.getEnterTime()))
                    .findFirst();

            Optionals.ifPresentOrElse(
                    optionalVehicleAccessRecord,
                    vehicleAccessRecord -> {
                        VehicleAccessRecord accessRecord = vehicleAccessRecordConverter.toVehicleAccessRecord(createVehicleAccessRecordForOutNanTouFeignDTO, vehicleAccessRecord.getId());
                        update.add(accessRecord);

                        if (judgeForPay(createVehicleAccessRecordForOutNanTouFeignDTO)) {
                            VehiclePayRecord vehiclePayRecord = payRecordConverter.toVehiclePayRecord(createVehicleAccessRecordForOutNanTouFeignDTO, vehicleAccessRecord.getRecordId());
                            payForAdd.add(vehiclePayRecord);
                        }
                    },
                    () -> {
                        VehicleAccessRecord vehicleAccessRecord = vehicleAccessRecordConverter.toVehicleAccessRecord(createVehicleAccessRecordForOutNanTouFeignDTO, projectBO);
                        add.add(vehicleAccessRecord);

                        if (judgeForPay(createVehicleAccessRecordForOutNanTouFeignDTO)) {
                            VehiclePayRecord vehiclePayRecord = payRecordConverter.toVehiclePayRecord(createVehicleAccessRecordForOutNanTouFeignDTO);
                            payForAdd.add(vehiclePayRecord);
                        }
                    });
        }

        if (!add.isEmpty()) {
            vehicleAccessRecordService.saveBatch(add);
        }
        if (!update.isEmpty()) {
            vehicleAccessRecordService.updateBatchById(update);
        }
        if (!payForAdd.isEmpty()) {
            vehiclePayRecordService.saveBatch(payForAdd);
        }
    }

}
